package com.sky.service.impl;

import com.github.pagehelper.Page;
import com.github.pagehelper.PageHelper;
import com.sky.constant.MessageConstant;
import com.sky.context.BaseContext;
import com.sky.dto.*;
import com.sky.entity.AddressBook;
import com.sky.entity.OrderDetail;
import com.sky.entity.Orders;
import com.sky.entity.ShoppingCart;
import com.sky.exception.AddressBookBusinessException;
import com.sky.exception.OrderBusinessException;
import com.sky.exception.ShoppingCartBusinessException;
import com.sky.mapper.AddressBookMapper;
import com.sky.mapper.OrdersMapper;
import com.sky.mapper.ShoppingCartMapper;
import com.sky.mapper.UserMapper;
import com.sky.result.PageResult;
import com.sky.service.OrdersService;
import com.sky.utils.SearchHttpAK;
import com.sky.vo.ConditionOrderPageVO;
import com.sky.vo.OrderStatisticsVO;
import com.sky.vo.OrderSubmitVO;
import com.sky.vo.OrdersPageQueryVO;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;

@Service
public class OrderServiceImpl implements OrdersService {
    @Autowired
    private OrdersMapper ordersMapper;
    @Autowired
    private ShoppingCartMapper shoppingCartMapper;
    @Autowired
    private AddressBookMapper addressBookMapper;
    @Autowired
    private UserMapper userMapper;
    @Autowired
    //百度地图util类
    private SearchHttpAK searchHttpAK;

    private Orders orders;
    @Override
    @Transactional
    public OrderSubmitVO submit(OrdersSubmitDTO ordersSubmitDTO) throws Exception {
        Orders order = new Orders();
        //获取当前用户Id
        long userId = BaseContext.getCurrentId();
        //获得当前用户的购物车
        List<ShoppingCart> shoppingCartList = shoppingCartMapper.selectByUserId(userId);
        //获取当前用户的地址簿信息
        List<AddressBook> addressBookList = addressBookMapper.list(userId);
        //判断异常情况：购物车为空/地址簿信息为空
        if(shoppingCartList == null) {
            throw new AddressBookBusinessException(MessageConstant.ADDRESS_BOOK_IS_NULL);
        }
        if(addressBookList.isEmpty() ) {
            throw new ShoppingCartBusinessException(MessageConstant.SHOPPING_CART_IS_NULL);
        }
        //把传输过来的订单数据赋值给订单对象
        BeanUtils.copyProperties(ordersSubmitDTO, order);
        //设置订单初始信息：1.订单状态为0(待付款) 2.支付状态为0(未支付) 3.下单用户id(userId)
        //4.下单时间（现在） 5.用户姓名（从user表查询） 6.收货人,手机号(从addressBook查询)
        // 7.订单号（当前时间的String格式）
        order.setStatus(Orders.PENDING_PAYMENT);
        order.setPayStatus(Orders.UN_PAID);
        order.setUserId(userId);
        order.setOrderTime(LocalDateTime.now());
        String name = userMapper.selectNameById(userId);
        //根据地址簿id查询地址簿信息
        AddressBook addressBook = addressBookMapper.get(ordersSubmitDTO.getAddressBookId());
        //user表里的名字，默认确实为空，因为没有相关权限拿到name
        order.setUserName(name);
        order.setConsignee(addressBook.getConsignee());
        order.setPhone(addressBook.getPhone());
        order.setNumber(String.valueOf(System.currentTimeMillis()));
        String FullAddress = addressBook.getFullAddress();
        //判断是否超出配送范围
            double distance = searchHttpAK.Util(FullAddress);
            //如果配送距离大于20公里，抛出异常
            if (distance > 20) throw new AddressBookBusinessException(MessageConstant.OUT_OF_RANGE);


        order.setAddress(FullAddress);
        //把orders作为全局变量，以便支付方法获取id
        orders = order;
        //插入一条订单数据
        ordersMapper.insert(order);
        //获取订单生成的id
        long orderId = order.getId();
        //初始化订单细节信息：大部分复制购物车信息，只有订单id需要拿到Order的返回主键
        List<OrderDetail> orderDetailList = new ArrayList<>();
        for(ShoppingCart shoppingCart : shoppingCartList) {
            OrderDetail orderDetail = new OrderDetail();
            orderDetail.setOrderId(orderId);
            BeanUtils.copyProperties(shoppingCart, orderDetail);
            orderDetailList.add(orderDetail);
        }
        //插入订单细节信息
        ordersMapper.insertBatchOrderDetail(orderDetailList);
        //构造返回的OrderVO对象
        OrderSubmitVO orderSubmitVO = new OrderSubmitVO();
        orderSubmitVO.setId(orderId);
        orderSubmitVO.setOrderNumber(order.getNumber());
        orderSubmitVO.setOrderAmount(order.getAmount());
        orderSubmitVO.setOrderTime(order.getOrderTime());
        return orderSubmitVO;
    }

    @Override
    public String payment(OrdersPaymentDTO ordersPaymentDTO) {
        //设置支付状态为1
        orders.setPayStatus(Orders.PAID);
        //设置订单状态为待接单
        orders.setStatus(Orders.TO_BE_CONFIRMED);
        //设置结账时间为现在
        orders.setCheckoutTime(LocalDateTime.now());
        //获取订单id
        long orderId = orders.getId();
        //更新订单信息
        ordersMapper.updateOrder(orders);

        return orders.getEstimatedDeliveryTime().toString();
    }

    @Override
    public PageResult page(Integer page, Integer pageSize, Integer status) {
        PageHelper.startPage(page, pageSize);
        Long userId = BaseContext.getCurrentId();
        //根据用户id拿到订单信息
        List<Orders> orders = ordersMapper.getOrdersByUserId(userId,status);
        //新建分页结果对象
        List<OrdersPageQueryVO> orderVOList = new ArrayList<>();
        //遍历订单信息，查询订单详情
        for (Orders order : orders) {
            List<OrderDetail> orderDetails = ordersMapper.getOrderDetailByOrderId(order.getId());
            OrdersPageQueryVO ordersPageQueryVO = new OrdersPageQueryVO();
            BeanUtils.copyProperties(order, ordersPageQueryVO);
            ordersPageQueryVO.setOrderDetailList(orderDetails);
            //把订单信息加入到分页结果对象中
            orderVOList.add(ordersPageQueryVO);
        }
        Page<OrdersPageQueryVO> p = new Page<>();
        p.addAll(orderVOList);
        p.setTotal(orderVOList.size());
        p.setPageNum(page);
        p.setPageSize(pageSize);
        PageResult pageResult = new PageResult(p.getTotal(), p.getResult());
        return pageResult;
    }

    @Override
    public OrdersPageQueryVO orderDetail(Long orderId) {
        List<OrderDetail> orderDetails = ordersMapper.getOrderDetailByOrderId(orderId);
        Orders order = ordersMapper.getOrdersByOrderId(orderId);
        OrdersPageQueryVO ordersPageQueryVO = new OrdersPageQueryVO();
        BeanUtils.copyProperties(order, ordersPageQueryVO);
        ordersPageQueryVO.setOrderDetailList(orderDetails);
        return ordersPageQueryVO;
    }

    @Override
    public void cancel(Long orderId) {
        Orders order = ordersMapper.getOrdersByOrderId(orderId);
        // 校验订单是否存在
        if (order == null) {
            throw new OrderBusinessException(MessageConstant.ORDER_NOT_FOUND);
        }
        //订单状态 1待付款 2待接单 3已接单 4派送中 5已完成 6已取消
        if (orders.getStatus() > 2) {
            throw new OrderBusinessException(MessageConstant.ORDER_STATUS_ERROR);
        }
        //设置订单状态为已取消
        order.setStatus(Orders.CANCELLED);
        //设置支付状态为退款
        order.setPayStatus(Orders.REFUND);
        //设置订单取消原因
        order.setCancelReason("用户取消订单");
        //设置取消时间
        order.setCancelTime(LocalDateTime.now());
        ordersMapper.updateOrder(order);
    }

    @Override
    public void repetition(Long id) {
        //拿到当前用户的ID
        long userId = BaseContext.getCurrentId();
        //根据订单id查询订单详细信息
        List<OrderDetail> orderDetailList = ordersMapper.getOrderDetailByOrderId(id);
        //把订单详细信息赋值给购物车
        List<ShoppingCart> shoppingCartList = new ArrayList<>();
        for (OrderDetail orderDetail : orderDetailList) {
            ShoppingCart shoppingCart = new ShoppingCart();
            BeanUtils.copyProperties(orderDetail, shoppingCart);
            shoppingCart.setUserId(userId);
            shoppingCartList.add(shoppingCart);
        }
        //插入购物车
        shoppingCartMapper.insertBatch(shoppingCartList);
    }

    @Override
    public PageResult ConditionSerachPage(OrdersPageQueryDTO ordersPageQueryDTO) {
        PageHelper.startPage(ordersPageQueryDTO.getPage(), ordersPageQueryDTO.getPageSize());
        //根据条件筛选订单信息
        List<Orders> orders = ordersMapper.getOrdersByCondition(ordersPageQueryDTO);
        //新建分页结果对象
        List<ConditionOrderPageVO> conditionOrderPageVOList = new ArrayList<>();
        //遍历订单信息，查询订单详情
        for (Orders order : orders) {
            List<OrderDetail> orderDetails = ordersMapper.getOrderDetailByOrderId(order.getId());
            ConditionOrderPageVO conditionOrderPageVO = new ConditionOrderPageVO();
            BeanUtils.copyProperties(order, conditionOrderPageVO);
            String orderDishesStr = getOrderDishesStr(order);
            conditionOrderPageVO.setOrderDishes(orderDishesStr);
            //把订单信息加入到分页结果对象中
            conditionOrderPageVOList.add(conditionOrderPageVO);
        }
        Page<ConditionOrderPageVO> p = new Page<>();
        p.addAll(conditionOrderPageVOList);
        p.setTotal(conditionOrderPageVOList.size());
        p.setPageNum(ordersPageQueryDTO.getPage());
        p.setPageSize(ordersPageQueryDTO.getPageSize());
        PageResult pageResult = new PageResult(p.getTotal(), p.getResult());

        return pageResult;
    }

    private String getOrderDishesStr(Orders orders) {
        // 查询订单菜品详情信息（订单中的菜品和数量）
        List<OrderDetail> orderDetailList =
                ordersMapper.getOrderDetailByOrderId(orders.getId());
        // 将每一条订单菜品信息拼接为字符串（格式：宫保鸡丁*3；）
        List<String> orderDishList = orderDetailList.stream().map(x -> {
            String orderDish = x.getName() + "*" + x.getNumber() + ";";
            return orderDish;
        }).collect(Collectors.toList());
        // 将该订单对应的所有菜品信息拼接在一起
        return String.join("", orderDishList);
    }

    @Override
    public OrderStatisticsVO getStatusStatistics() {
        OrderStatisticsVO orderStatisticsVO = new OrderStatisticsVO();
        //获取各个状态的订单数量
        orderStatisticsVO.setToBeConfirmed(ordersMapper.getStatusStatistics(Orders.TO_BE_CONFIRMED));
        orderStatisticsVO.setConfirmed(ordersMapper.getStatusStatistics(Orders.CONFIRMED));
        orderStatisticsVO.setDeliveryInProgress(ordersMapper.getStatusStatistics(Orders.DELIVERY_IN_PROGRESS));
        return orderStatisticsVO;

    }

    @Override
    public void confrimOrder(Long orderId) {
        Orders order = ordersMapper.getOrdersByOrderId(orderId);
        order.setStatus(Orders.CONFIRMED);
        ordersMapper.updateOrder(order);
    }

    @Override
    public void deliveryOrder(Long orderId) {
        Orders order = ordersMapper.getOrdersByOrderId(orderId);
        order.setStatus(Orders.DELIVERY_IN_PROGRESS);
        ordersMapper.updateOrder(order);
    }

    @Override
    public void completeOrder(Long orderId) {
        Orders order = ordersMapper.getOrdersByOrderId(orderId);
        //只有订单状态为派送中的订单才能设置为已完成
        if(order.getStatus() != Orders.DELIVERY_IN_PROGRESS) {
            throw new OrderBusinessException(MessageConstant.ORDER_STATUS_ERROR);
        }
        order.setStatus(Orders.COMPLETED);
        ordersMapper.updateOrder(order);
    }

    @Override
    public void rejectionOrder(OrdersRejectionDTO ordersRejectionDTO) {
        Orders order = ordersMapper.getOrdersByOrderId(ordersRejectionDTO.getId());
        //判断是否为已支付订单(订单状态为待支付，或者订单支付状态为待付款)，设置订单状态为已取消
        if(order.getStatus() == Orders.PENDING_PAYMENT || order.getPayStatus() == Orders.UN_PAID) {
            order.setStatus(Orders.CANCELLED);
        }else {
            //若已支付，则设置支付状态为退款，订单状态为已取消
            order.setStatus(Orders.CANCELLED);
            order.setPayStatus(Orders.REFUND);
        }
        //设置订单拒绝原因
        order.setRejectionReason(ordersRejectionDTO.getRejectionReason());
        ordersMapper.updateOrder(order);
    }

    @Override
    public void cancel(OrdersCancelDTO ordersCancelDTO) {
        Orders order = ordersMapper.getOrdersByOrderId(ordersCancelDTO.getId());
        //如果已付款，则申请退款
        if(order.getPayStatus() == Orders.PAID) {
            order.setPayStatus(Orders.REFUND);
        }
        //设置订单状态为已取消
        order.setStatus(Orders.CANCELLED);
        order.setCancelReason(ordersCancelDTO.getCancelReason());
        order.setCancelTime(LocalDateTime.now());
        ordersMapper.updateOrder(order);
    }
}
